package Day_0228.TCPIP;

/**
 * @author zxc
 * @date 2023/02/28 21:48
 **/
public class TCPIP_Common_InterviewQuestions {
    public static void main(String[] args) {
        /**
         * 三次握手、四次挥手的常见面试题
         * ===
         * 问题1 ：为什么关闭连接的需要四次挥手，而建立连接却只要三次握手呢？
         * （1）关闭连接时，被动断开方在收到对方的FIN结束请求报文时，很可能业务数据没有发送完成，并不能立即关闭连接，
         *  被动方只能先回复一个ACK响应报文，告诉主动断开方：“你发的FIN报文我收到了，只有等到我所有的业务报文都发送完了，
         *  我才能真正的结束，在结束之前，我会发你FIN+ACK报文的，你先等着”。
         *  ===》
         *  所以，被动断开方的确认报文，需要拆开成为两步，故总体就需要四步挥手。
         *
         * （2）而在建立连接场景中，Server端的应答可以稍微简单一些。
         *  当Server端收到Client端的SYN连接请求报文后，其中ACK报文表示对请求报文的应答，
         *  SYN报文用来表示服务端的连接也已经同步开启了，而ACK报文和SYN报文之间，不会有其他报文需要发送，故而可以合二为一，
         *  可以直接发送一个SYN+ACK报文。所以，在建立连接时，只需要三次握手即可。
         *
         *
         * 问题（2）：为什么连接建立的时候是三次握手，可以改成两次握手吗？
         * 1.三次握手完成两个重要的功能：
         * （1）一是双方都做好发送数据的准备工作，而且双方都知道对方已准备好；
         * （2）二是双方完成初始SN序列号的协商，双方的SN序列号在握手过程中被发送和确认。
         *
         * 2.如果把三次握手改成两次握手，可能发生死锁。
         * 两次握手的话，缺失了Client的二次确认ACK帧，假想的TCP建立的连接时二次挥手。
         *
         * 3.在假想的TCP建立的连接时二次握手过程中，Client发送Server发送一个SYN请求帧，Server收到后发送了确认应答SYN+ACK帧。
         * （1）按照两次握手的协定，Server认为连接已经成功地建立了，可以开始发送数据帧。
         * （2）这个过程中，如果确认应答SYN+ACK帧在传输中被丢失，Client没有收到，
         *  Client将不知道Server是否已准备好，也不知道Server的SN序列号，
         *  Client认为连接还未建立成功，将忽略Server发来的任何数据分组，会一直等待Server的SYN+ACK确认应答帧。
         * （3）而Server在发出的数据帧后，一直没有收到对应的ACK确认后就会产生超时，重复发送同样的数据帧。这样就形成了死锁。
         *
         *
         * 问题（3）：为什么主动断开方在TIME-WAIT状态必须等待2MSL的时间？
         * 1.原因之一：
         * （1）主动断开方等待2MSL的时间，是为了确保两端都能最终关闭。
         * （2）假设网络是不可靠的，被动断开方发送FIN+ACK报文后，其主动方的ACK响应报文有可能丢失，
         *  这时候的被动断开方处于LAST-ACK状态的，由于收不到ACK确认被动方一直不能正常的进入CLOSED状态。
         * （3）在这种场景下，被动断开方会超时重传FIN+ACK断开响应报文，
         *  如果主动断开方在2MSL时间内，收到这个重传的FIN+ACK报文，会重传一次ACK报文，后再一次重新启动2MSL计时等待，
         *  ===》
         *  这样，就能确保被动断开方能收到ACK报文，从而能确保被动方顺利进入到CLOSED状态。
         *  只有这样，双方都能够确保关闭。
         * （4）反过来说，如果主动断开方在发送完ACK响应报文后，不是进入TIME_WAIT状态去等待2MSL时间，而是立即释放连接，
         *  则将无法收到被动方重传的FIN+ACK报文，所以不会再发送一次ACK确认报文，
         *  此时处于LAST-ACK状态的被动断开方，无法正常进入到CLOSED状态。
         *
         * 2.原因之二：
         * （1）防止“旧连接的已失效的数据报文”出现在新连接中。
         * （2）主动断开方在发送完最后一个ACK报文后，再经过2MSL，才能最终关闭和释放端口，
         *  ===》
         *  这就意味着，相同端口的新TCP新连接，需要在2MSL的时间之后，才能够正常的建立。
         * （3）2MSL这段时间内，旧连接所产生的所有数据报文，都已经从网络中消失了，
         *  从而，确保了下一个新的连接中不会出现这种旧连接请求报文。
         *
         *
         * 问题（4）：如果已经建立了连接，但是Client端突然出现故障了怎么办？
         * （1）TCP还设有一个保活计时器，Client端如果出现故障，Server端不能一直等下去，这样会浪费系统资源。
         * （2）每收到一次Client客户端的数据帧后，Server端都的保活计时器会复位。
         * （3）计时器的超时时间通常是设置为2小时，
         *  若2小时还没有收到Client端的任何数据帧，Server端就会发送一个探测报文段，以后每隔75秒钟发送一次。
         *  若一连发送10个探测报文仍然没反应，Server端就认为Client端出了故障，接着就关闭连接。
         * （4）如果觉得保活计时器的两个多小时的间隔太长，可以自行调整TCP连接的保活参数。
         *
         *
         */
    }
}
